package org.study.bookmanager.middlewares;

import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
//import org.study.bookmanager.service.JwtUserDetailsService;
import org.study.bookmanager.service.impl.JwtUserDetailsServiceImpl;
import org.study.bookmanager.utils.JwtUtils;

import java.io.IOException;


@Component
@Slf4j
public class JwtFilter extends OncePerRequestFilter {
//继承OncePerRequestFilter表示每次请求过滤一次，用于快速编写JWT校验规则

    @Resource
    private JwtUserDetailsServiceImpl jwtUserDetailsServiceImpl;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();

        // 如果请求路径不需要进行 JWT 鉴权，直接放行请求
//        if (!requestURI.startsWith("/v1/user/")) {
//            filterChain.doFilter(request, response);
//            return;
//        }

        //首先从Header中取出JWT
        String authorization = request.getHeader("Authorization");
        //判断是否包含JWT且格式正确
        if (authorization != null && authorization.startsWith("Bearer ")) {
            String token = authorization.substring(7);
            //开始解析成UserDetails对象，如果得到的是null说明解析失败，JWT有问题
            String userName=JwtUtils.getUserName(token);
            // 加载与令 token 关联的用户
            if(userName != null) {
                UserDetails userDetails = jwtUserDetailsServiceImpl.loadUserByUsername(userName);
                //验证没有问题，那么就可以开始创建Authentication了，这里我们跟默认情况保持一致
                //使用UsernamePasswordAuthenticationToken作为实体，填写相关用户信息进去
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userDetails, null, null);
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                //然后直接把配置好的Authentication塞给SecurityContext表示已经完成验证
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}